Uvod

Ovo je domaći zadatak nakon dvodnevnog DS boot camp-a.
Koristićemo podatke o svim učesnicima na olimpijadama.
Podaci se nalaze na linku: https://github.com/TanjaKec/RMarkdown4RR

Task #1. Struktura podataka

Učitajmo podatke iz csv fajla

athlete_events <- read.csv(here(params$data),encoding = "UTF-8")

Pogledajmo strukturu podataka koristeći funkciju glimpse().

glimpse(athlete_events)
## Observations: 271,116
## Variables: 15
## $ ID     <int> 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, ...
## $ Name   <fct> A Dijiang, A Lamusi, Gunnar Nielsen Aaby, Edgar Lindenau Aab...
## $ Sex    <fct> M, M, M, M, F, F, F, F, F, F, M, M, M, M, M, M, M, M, M, M, ...
## $ Age    <int> 24, 23, 24, 34, 21, 21, 25, 25, 27, 27, 31, 31, 31, 31, 33, ...
## $ Height <int> 180, 170, NA, NA, 185, 185, 185, 185, 185, 185, 188, 188, 18...
## $ Weight <dbl> 80, 60, NA, NA, 82, 82, 82, 82, 82, 82, 75, 75, 75, 75, 75, ...
## $ Team   <fct> China, China, Denmark, Denmark/Sweden, Netherlands, Netherla...
## $ NOC    <fct> CHN, CHN, DEN, DEN, NED, NED, NED, NED, NED, NED, USA, USA, ...
## $ Games  <fct> 1992 Summer, 2012 Summer, 1920 Summer, 1900 Summer, 1988 Win...
## $ Year   <int> 1992, 2012, 1920, 1900, 1988, 1988, 1992, 1992, 1994, 1994, ...
## $ Season <fct> Summer, Summer, Summer, Summer, Winter, Winter, Winter, Wint...
## $ City   <fct> Barcelona, London, Antwerpen, Paris, Calgary, Calgary, Alber...
## $ Sport  <fct> Basketball, Judo, Football, Tug-Of-War, Speed Skating, Speed...
## $ Event  <fct> "Basketball Men's Basketball", "Judo Men's Extra-Lightweight...
## $ Medal  <fct> NA, NA, NA, Gold, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...

Task #2. Filtriranje varijabli

U ovom primeru ćemo selektovati sve varijable koje se završavaju na slovo t, a počinju slovom s. Napravićemo data frame myData koji zadovoljava traženi uslov:

myData <- select(athlete_events, ends_with("t"))%>%
          select(,starts_with("S"))
head(myData, n = 3)
Sport
Basketball
Judo
Football

Dakle, prvo smo korišćenjem funkcije select() izdvojili sve varijable koje se završavaju slovom t (ends_with).

Zatim smo rezultat te operacije prosledili drugoj select() funkciji u kojoj smo sada izdvojili one varijable koje počinju slovom S (starts_with).

Ovaj rezultat smo upisali u data frame myData.

Na kraju smo korišćenjem funkcije head() prikazali prva tri reda našeg data frame-a.

Task #3. Kreiranje novih varijabli

Potrebno je da kreiramo varijablu Body Mass Index (BMI) (\(kg/m^2\)) koja se računa po sledećoj formuli: \[BMI=Weight/(Height/100)^2\] Za ovu operaciju koristi se funkcija mutate().

Našem data frame-u athlete_events dodaćemo varijablu BMI:

athlete_events <- mutate(athlete_events,BMI=Weight/(Height/100)^2)
head(athlete_events,5)
ID Name Sex Age Height Weight Team NOC Games Year Season City Sport Event Medal BMI
1 A Dijiang M 24 180 80 China CHN 1992 Summer 1992 Summer Barcelona Basketball Basketball Men’s Basketball NA 24.69136
2 A Lamusi M 23 170 60 China CHN 2012 Summer 2012 Summer London Judo Judo Men’s Extra-Lightweight NA 20.76125
3 Gunnar Nielsen Aaby M 24 NA NA Denmark DEN 1920 Summer 1920 Summer Antwerpen Football Football Men’s Football NA NA
4 Edgar Lindenau Aabye M 34 NA NA Denmark/Sweden DEN 1900 Summer 1900 Summer Paris Tug-Of-War Tug-Of-War Men’s Tug-Of-War Gold NA
5 Christine Jacoba Aaftink F 21 185 82 Netherlands NED 1988 Winter 1988 Winter Calgary Speed Skating Speed Skating Women’s 500 metres NA 23.95909

Task #4. Filtriranje podataka

U ovom zadatku ćemo napraviti dva nova data frame-a, koje ćemo dobiti filtriranjem podataka iz data frame-a athlete_events, korišćenjem funkcije filter().

Prvi data frame olympicSR treba da sadrži podatke o svim učesnicima iz Srbije:

olympicSR <- filter(athlete_events,Team=="Serbia")
head(olympicSR,5)
ID Name Sex Age Height Weight Team NOC Games Year Season City Sport Event Medal BMI
2516 Aleksandar Aleksi M 20 188 89 Serbia SRB 2012 Summer 2012 Summer London Canoeing Canoeing Men’s Kayak Fours, 1,000 metres NA 25.18108
2517 Milan Aleksi M 26 193 96 Serbia SRB 2012 Summer 2012 Summer London Water Polo Water Polo Men’s Water Polo Bronze 25.77250
2517 Milan Aleksi M 30 193 96 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Water Polo Water Polo Men’s Water Polo Gold 25.77250
5346 Andrea Arsovi F 25 165 61 Serbia SRB 2012 Summer 2012 Summer London Shooting Shooting Women’s Air Rifle, 10 metres NA 22.40588
5346 Andrea Arsovi F 25 165 61 Serbia SRB 2012 Summer 2012 Summer London Shooting Shooting Women’s Small-Bore Rifle, Three Positions, 50 metres NA 22.40588

Drugi data frame olympicSR21c treba da sadrži podatke o svim učesnicima iz Srbije koji su učestvovali na olimpijadama počev od 2000. godine i koji imaju preko 100Kg težine i preko 2m visine:

olympicSR21c <- filter(olympicSR,Year>=2000 & Weight>100 & Height>200)
head(olympicSR21c,5)
ID Name Sex Age Height Weight Team NOC Games Year Season City Sport Event Medal BMI
11656 Stefan Birevi M 26 210 104 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Basketball Basketball Men’s Basketball Silver 23.58277
16420 Aleksandar Bundalo M 24 205 109 Serbia SRB 2014 Winter 2014 Winter Sochi Bobsleigh Bobsleigh Men’s Two NA 25.93694
39748 Andrija Geri M 31 203 101 Serbia SRB 2008 Summer 2008 Summer Beijing Volleyball Volleyball Men’s Volleyball NA 24.50921
55550 Nikola Joki M 21 209 115 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Basketball Basketball Men’s Basketball Silver 26.32724
56863 Nikola Kalini M 24 202 102 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Basketball Basketball Men’s Basketball Silver 24.99755

Task #5. Sortiranje podataka

Za sortiranje podataka u data frame-u koristi se funkcija arrange().

Sortirajmo podatke u data frame-u olympicSR21c po rastućoj vrednosti varijable Height:

olympicSR21c <- arrange(olympicSR21c,Height)
head(olympicSR21c,5)
ID Name Sex Age Height Weight Team NOC Games Year Season City Sport Event Medal BMI
56863 Nikola Kalini M 24 202 102 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Basketball Basketball Men’s Basketball Silver 24.99755
74340 Duan Mandi M 18 202 105 Serbia SRB 2012 Summer 2012 Summer London Water Polo Water Polo Men’s Water Polo Bronze 25.73277
74340 Duan Mandi M 22 202 105 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Water Polo Water Polo Men’s Water Polo Gold 25.73277
39748 Andrija Geri M 31 203 101 Serbia SRB 2008 Summer 2008 Summer Beijing Volleyball Volleyball Men’s Volleyball NA 24.50921
16420 Aleksandar Bundalo M 24 205 109 Serbia SRB 2014 Winter 2014 Winter Sochi Bobsleigh Bobsleigh Men’s Two NA 25.93694

Sortirajmo sada podatke u data frame-u olympicSR21c po opadajućoj vrednosti varijable Height:

olympicSR21c <- arrange(olympicSR21c,desc(Height))
head(olympicSR21c,5)
ID Name Sex Age Height Weight Team NOC Games Year Season City Sport Event Medal BMI
98227 Miroslav Raduljica M 28 213 130 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Basketball Basketball Men’s Basketball Silver 28.65393
115246 Vladimir timac M 28 211 112 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Basketball Basketball Men’s Basketball Silver 25.15667
11656 Stefan Birevi M 26 210 104 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Basketball Basketball Men’s Basketball Silver 23.58277
55550 Nikola Joki M 21 209 115 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Basketball Basketball Men’s Basketball Silver 26.32724
16420 Aleksandar Bundalo M 24 205 109 Serbia SRB 2014 Winter 2014 Winter Sochi Bobsleigh Bobsleigh Men’s Two NA 25.93694

Task #6. Još malo sortiranja

Iskoristimo sortiranje kako bismo pronašli najmlađeg i najstarijeg sportistu u data frame-u olympicSR.

Kako bismo pronašli najmlađeg sportistu, sortiraćemo date frame u rastućem redosledu po varijabli Age i prikazati samo prvi red:

olympicSR <- arrange(olympicSR,Age)
head(olympicSR,1)
ID Name Sex Age Height Weight Team NOC Games Year Season City Sport Event Medal BMI
23792 Anja Crevar F 16 164 49 Serbia SRB 2016 Summer 2016 Summer Rio de Janeiro Swimming Swimming Women’s 200 metres Individual Medley NA 18.21832

slično, da bismo pronašli najstarijeg sportistu, sortiraćemo date frame u opadajućem redosledu po varijabli Age i prikazati samo prvi red:

olympicSR <- arrange(olympicSR,desc(Age))
head(olympicSR,1)
ID Name Sex Age Height Weight Team NOC Games Year Season City Sport Event Medal BMI
108383 Jasna ekari (Brajkovi-) F 46 175 70 Serbia SRB 2012 Summer 2012 Summer London Shooting Shooting Women’s Sporting Pistol, 25 metres NA 22.85714

Task #7. Sumiranje podataka

Za sumiranje podataka u data frame-u koriste se sledeće funkcije:
Objective Function Description
basic sum(x) Sum of vector x
centre mean(x) Mean (average) of vector x
median(x) Median of vector x
spread sd(x) Standard deviation of vector x
quantile(x, probs) Quantile of vector x
range(x) Range of vector x
diff(range(x))) Width of the range of vector x
min(x) Min of vector x
max(x) Max of vector x
abs(x) Absolute value of a number x

U našem primeru ćemo sumirati podatke data frame-a olympicSR.

Prvo ćemo pronaći dve sumarne varijable: max_Age i max_BMI:

summarise(olympicSR,max_Age=max(Age),max_BMI=max(BMI))
max_Age max_BMI
46 40.03546

Sada pronađimo mean_Age i mean_BMI:

summarise(olympicSR,mean_Age=mean(Age),mean_BMI=mean(BMI))
mean_Age mean_BMI
26.38918 23.34068

Task #8. Vizuelizacija podataka

Prikažimo tabelarno broj osvojenih medalja na svim olimpijskim igrama po timovima:

athlete_events %>% 
  filter(!is.na(Medal)) %>% 
  group_by(NOC, Medal) %>% 
  summarize(cases=n()) %>% 
  DT::datatable()

Napravimo novi data frame Countries koji će u jednom redu prikazati sledeće podatke: Team, NOC, Year, Athletes, Gold, Silver, Bronze

countries <- athlete_events %>% 
  mutate(Medal=forcats::fct_explicit_na(Medal,na_level = "NoMedal")) %>% 
  group_by(Team, NOC, Year, Medal) %>% 
  summarize(Cases=n()) %>% 
  spread(,key = "Medal", value = "Cases") %>% 
  mutate(Athletes=sum(Gold,Silver,Bronze,NoMedal,na.rm = TRUE))
countries %>% 
  DT::datatable()

Pokušajmo da prikažemo zemlje učesnice svih olimpijada sortirane po broju bodova koje dobijamo sledećom formulom: \[Points=3*Gold + 2*Silver + Bronze\]

countries <- mutate(countries,Points=sum(3*Gold,2*Silver,Bronze,na.rm = TRUE)) %>% 
  group_by(NOC) %>% 
  summarize(
      Athletes=sum(Athletes,na.rm = TRUE), 
      Gold=sum(Gold,na.rm = TRUE),
      Silver=sum(Silver,na.rm = TRUE),
      Bronze=sum(Bronze,na.rm = TRUE),
      Points=sum(Points,na.rm = TRUE)
  )
arrange(countries,desc(Points)) %>% 
  DT::datatable()

Sada ćemo na mapi sveta prikazati broj poena po zemljama.

U tu svrhu ćemo koristiti pakete rnaturalearth i rnaturalearthdata

library("rnaturalearth")
library("rnaturalearthdata")

Iz ovih paketa ćemo kreirati data frame world:

world <- ne_countries(scale = "medium", returnclass = "sf")
class(world)
## [1] "sf"         "data.frame"

Pogledajmo šta sadrži ovaj data frame:

glimpse(world)
## Observations: 241
## Variables: 64
## $ scalerank  <int> 3, 1, 1, 1, 1, 3, 3, 1, 1, 1, 3, 1, 5, 3, 1, 1, 1, 1, 1,...
## $ featurecla <chr> "Admin-0 country", "Admin-0 country", "Admin-0 country",...
## $ labelrank  <dbl> 5, 3, 3, 6, 6, 6, 6, 4, 2, 6, 4, 4, 5, 6, 6, 2, 4, 5, 6,...
## $ sovereignt <chr> "Netherlands", "Afghanistan", "Angola", "United Kingdom"...
## $ sov_a3     <chr> "NL1", "AFG", "AGO", "GB1", "ALB", "FI1", "AND", "ARE", ...
## $ adm0_dif   <dbl> 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0,...
## $ level      <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ type       <chr> "Country", "Sovereign country", "Sovereign country", "De...
## $ admin      <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
## $ adm0_a3    <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
## $ geou_dif   <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ geounit    <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
## $ gu_a3      <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
## $ su_dif     <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ subunit    <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
## $ su_a3      <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
## $ brk_diff   <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ name       <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
## $ name_long  <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
## $ brk_a3     <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
## $ brk_name   <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
## $ brk_group  <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ abbrev     <chr> "Aruba", "Afg.", "Ang.", "Ang.", "Alb.", "Aland", "And."...
## $ postal     <chr> "AW", "AF", "AO", "AI", "AL", "AI", "AND", "AE", "AR", "...
## $ formal_en  <chr> "Aruba", "Islamic State of Afghanistan", "People's Repub...
## $ formal_fr  <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ note_adm0  <chr> "Neth.", NA, NA, "U.K.", NA, "Fin.", NA, NA, NA, NA, "U....
## $ note_brk   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Multiple cl...
## $ name_sort  <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
## $ name_alt   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ mapcolor7  <dbl> 4, 5, 3, 6, 1, 4, 1, 2, 3, 3, 4, 4, 1, 7, 2, 1, 3, 1, 2,...
## $ mapcolor8  <dbl> 2, 6, 2, 6, 4, 1, 4, 1, 1, 1, 5, 5, 2, 5, 2, 2, 1, 6, 2,...
## $ mapcolor9  <dbl> 2, 8, 6, 6, 1, 4, 1, 3, 3, 2, 1, 1, 2, 9, 5, 2, 3, 5, 5,...
## $ mapcolor13 <dbl> 9, 7, 1, 3, 6, 6, 8, 3, 13, 10, 1, NA, 7, 11, 5, 7, 4, 8...
## $ pop_est    <dbl> 103065, 28400000, 12799293, 14436, 3639453, 27153, 83888...
## $ gdp_md_est <dbl> 2258.0, 22270.0, 110300.0, 108.9, 21810.0, 1563.0, 3660....
## $ pop_year   <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ lastcensus <dbl> 2010, 1979, 1970, NA, 2001, NA, 1989, 2010, 2010, 2001, ...
## $ gdp_year   <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ economy    <chr> "6. Developing region", "7. Least developed region", "7....
## $ income_grp <chr> "2. High income: nonOECD", "5. Low income", "3. Upper mi...
## $ wikipedia  <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ fips_10    <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ iso_a2     <chr> "AW", "AF", "AO", "AI", "AL", "AX", "AD", "AE", "AR", "A...
## $ iso_a3     <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", ...
## $ iso_n3     <chr> "533", "004", "024", "660", "008", "248", "020", "784", ...
## $ un_a3      <chr> "533", "004", "024", "660", "008", "248", "020", "784", ...
## $ wb_a2      <chr> "AW", "AF", "AO", NA, "AL", NA, "AD", "AE", "AR", "AM", ...
## $ wb_a3      <chr> "ABW", "AFG", "AGO", NA, "ALB", NA, "ADO", "ARE", "ARG",...
## $ woe_id     <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ adm0_a3_is <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", ...
## $ adm0_a3_us <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
## $ adm0_a3_un <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ adm0_a3_wb <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
## $ continent  <chr> "North America", "Asia", "Africa", "North America", "Eur...
## $ region_un  <chr> "Americas", "Asia", "Africa", "Americas", "Europe", "Eur...
## $ subregion  <chr> "Caribbean", "Southern Asia", "Middle Africa", "Caribbea...
## $ region_wb  <chr> "Latin America & Caribbean", "South Asia", "Sub-Saharan ...
## $ name_len   <dbl> 5, 11, 6, 8, 7, 5, 7, 20, 9, 7, 14, 10, 23, 22, 17, 9, 7...
## $ long_len   <dbl> 5, 11, 6, 8, 7, 13, 7, 20, 9, 7, 14, 10, 27, 35, 19, 9, ...
## $ abbrev_len <dbl> 5, 4, 4, 4, 4, 5, 4, 6, 4, 4, 9, 4, 7, 10, 6, 4, 5, 4, 4...
## $ tiny       <dbl> 4, NA, NA, NA, NA, 5, 5, NA, NA, NA, 3, NA, NA, 2, 4, NA...
## $ homepart   <dbl> NA, 1, 1, NA, 1, NA, 1, 1, 1, 1, NA, 1, NA, NA, 1, 1, 1,...
## $ geometry   <MULTIPOLYGON [arc_degree]> MULTIPOLYGON (((-69.89912 1..., MU...

Možemo videti da se naš prethodni data frame countries može povezati sa data frame-om world preko polja NOC i iso_a3, pa ćemo povezati ove data frame-ove:

allData <- merge(world,countries,by.x="iso_a3",by.y="NOC",all.x = TRUE)
allData %>% 
  select(-geometry) %>% 
  DT::datatable()
## Warning in instance$preRenderHook(instance): It seems your data is too big
## for client-side DataTables. You may consider server-side processing: https://
## rstudio.github.io/DT/server.html

Prikažimo broj poena na mapi:

ggplot(data = allData) +
    geom_sf(aes(fill = Points)) +
    scale_fill_viridis_c(option = "plasma", trans = "sqrt")

Kako u našem data frame-u imamo i broj stanovnika u zemlji, izračunajmo i prosečan broj poena na 1000 stanovnika.

allData <- mutate(allData,PointsPer1000Capita=Points/pop_est*1000) 

allData %>% 
  select(-geometry) %>% 
  DT::datatable()
## Warning in instance$preRenderHook(instance): It seems your data is too big
## for client-side DataTables. You may consider server-side processing: https://
## rstudio.github.io/DT/server.html

Na kraju, prikažimo i to na mapi:

ggplot(data = allData) +
    geom_sf(aes(fill = PointsPer1000Capita)) +
    scale_fill_viridis_c(option = "plasma", trans = "sqrt")

LS0tDQp0aXRsZTogIkNhc2VTdHVkeUhXIg0KYXV0aG9yOiAiTWlsYW4gxJB1cmV0YW5vdmnEhyINCmRhdGU6ICcwNy4wNC4yMDIwJw0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0aGVtZTogImZsYXRseSINCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgZGZfcHJpbnQ6IGthYmxlDQpwYXJhbXM6DQogIGRhdGE6ICJkYXRhL2F0aGxldGVfZXZlbnRzLmNzdiINCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShoZXJlKSAjIGZvciBmaWxlIHBhdGhzDQpsaWJyYXJ5KHRpZHl2ZXJzZSkgIyBmb3IgYWxsIGVsc2UNCnRoZW1lX3NldCh0aGVtZV9taW5pbWFsKCkpDQpgYGANCiMjIFV2b2QNCg0KT3ZvIGplIGRvbWHEh2kgemFkYXRhayBuYWtvbiBkdm9kbmV2bm9nICoqRFMgYm9vdCBjYW1wKiotYS48YnI+DQpLb3Jpc3RpxIdlbW8gcG9kYXRrZSBvIHN2aW0gdcSNZXNuaWNpbWEgbmEgb2xpbXBpamFkYW1hLjxicj4NClBvZGFjaSBzZSBuYWxhemUgbmEgbGlua3U6IFtodHRwczovL2dpdGh1Yi5jb20vVGFuamFLZWMvUk1hcmtkb3duNFJSXShodHRwczovL2dpdGh1Yi5jb20vVGFuamFLZWMvUk1hcmtkb3duNFJSKQ0KDQoNCiMjIFRhc2sgIzEuIFN0cnVrdHVyYSBwb2RhdGFrYQ0KDQpVxI1pdGFqbW8gcG9kYXRrZSBpeiBjc3YgZmFqbGENCmBgYHtyfQ0KYXRobGV0ZV9ldmVudHMgPC0gcmVhZC5jc3YoaGVyZShwYXJhbXMkZGF0YSksZW5jb2RpbmcgPSAiVVRGLTgiKQ0KYGBgDQpQb2dsZWRham1vIHN0cnVrdHVydSBwb2RhdGFrYSBrb3Jpc3RlxIdpIGZ1bmtjaWp1IGBnbGltcHNlKClgLg0KYGBge3J9DQpnbGltcHNlKGF0aGxldGVfZXZlbnRzKQ0KYGBgDQoNCiMjIFRhc2sgIzIuIEZpbHRyaXJhbmplIHZhcmlqYWJsaQ0KDQpVIG92b20gcHJpbWVydSDEh2VtbyBzZWxla3RvdmF0aSBzdmUgdmFyaWphYmxlIGtvamUgc2UgemF2csWhYXZhanUgbmEgc2xvdm8gKipgdGAqKiwgYSBwb8SNaW5qdSBzbG92b20gKipgc2AqKi4NCk5hcHJhdmnEh2VtbyBkYXRhIGZyYW1lICoqbXlEYXRhKioga29qaSB6YWRvdm9samF2YSB0cmHFvmVuaSB1c2xvdjogIA0KDQpgYGB7cn0NCm15RGF0YSA8LSBzZWxlY3QoYXRobGV0ZV9ldmVudHMsIGVuZHNfd2l0aCgidCIpKSU+JQ0KICAgICAgICAgIHNlbGVjdCgsc3RhcnRzX3dpdGgoIlMiKSkNCmhlYWQobXlEYXRhLCBuID0gMykNCmBgYA0KRGFrbGUsIHBydm8gc21vIGtvcmnFocSHZW5qZW0gZnVua2NpamUgYHNlbGVjdCgpYCBpemR2b2ppbGkgc3ZlIHZhcmlqYWJsZSBrb2plIHNlIHphdnLFoWF2YWp1IHNsb3ZvbSAqKmB0YCoqIChgZW5kc193aXRoYCkuDQoNClphdGltIHNtbyByZXp1bHRhdCB0ZSBvcGVyYWNpamUgcHJvc2xlZGlsaSBkcnVnb2ogYHNlbGVjdCgpYCBmdW5rY2lqaSB1IGtvam9qIHNtbyBzYWRhIGl6ZHZvamlsaSBvbmUgdmFyaWphYmxlIGtvamUgcG/EjWluanUgc2xvdm9tICoqYFNgKiogKGBzdGFydHNfd2l0aGApLg0KDQpPdmFqIHJlenVsdGF0IHNtbyB1cGlzYWxpIHUgZGF0YSBmcmFtZSBgbXlEYXRhYC4NCg0KTmEga3JhanUgc21vIGtvcmnFocSHZW5qZW0gZnVua2NpamUgYGhlYWQoKWAgcHJpa2F6YWxpIHBydmEgdHJpIHJlZGEgbmHFoWVnIGRhdGEgZnJhbWUtYS4NCg0KIyMgVGFzayAjMy4gS3JlaXJhbmplIG5vdmloIHZhcmlqYWJsaQ0KDQpQb3RyZWJubyBqZSBkYSBrcmVpcmFtbyB2YXJpamFibHUgKioqQm9keSBNYXNzIEluZGV4IChCTUkpKioqICgka2cvbV4yJCkga29qYSBzZSByYcSNdW5hIHBvIHNsZWRlxIdvaiBmb3JtdWxpOg0KJCRCTUk9V2VpZ2h0LyhIZWlnaHQvMTAwKV4yJCQNClphIG92dSBvcGVyYWNpanUga29yaXN0aSBzZSBmdW5rY2lqYSBgbXV0YXRlKClgLg0KDQpOYcWhZW0gZGF0YSBmcmFtZS11IGBhdGhsZXRlX2V2ZW50c2AgZG9kYcSHZW1vIHZhcmlqYWJsdSBCTUk6DQpgYGB7cn0NCmF0aGxldGVfZXZlbnRzIDwtIG11dGF0ZShhdGhsZXRlX2V2ZW50cyxCTUk9V2VpZ2h0LyhIZWlnaHQvMTAwKV4yKQ0KaGVhZChhdGhsZXRlX2V2ZW50cyw1KQ0KYGBgDQoNCiMjIFRhc2sgIzQuIEZpbHRyaXJhbmplIHBvZGF0YWthDQoNClUgb3ZvbSB6YWRhdGt1IMSHZW1vIG5hcHJhdml0aSBkdmEgbm92YSBkYXRhIGZyYW1lLWEsIGtvamUgxIdlbW8gZG9iaXRpIGZpbHRyaXJhbmplbSBwb2RhdGFrYSBpeiBkYXRhIGZyYW1lLWEgYGF0aGxldGVfZXZlbnRzYCwga29yacWhxIdlbmplbSBmdW5rY2lqZSBgZmlsdGVyKClgLg0KDQpQcnZpIGRhdGEgZnJhbWUgYG9seW1waWNTUmAgdHJlYmEgZGEgc2FkcsW+aSBwb2RhdGtlIG8gc3ZpbSB1xI1lc25pY2ltYSBpeiBTcmJpamU6DQpgYGB7cn0NCm9seW1waWNTUiA8LSBmaWx0ZXIoYXRobGV0ZV9ldmVudHMsVGVhbT09IlNlcmJpYSIpDQpoZWFkKG9seW1waWNTUiw1KQ0KYGBgDQoNCkRydWdpIGRhdGEgZnJhbWUgYG9seW1waWNTUjIxY2AgdHJlYmEgZGEgc2FkcsW+aSBwb2RhdGtlIG8gc3ZpbSB1xI1lc25pY2ltYSBpeiBTcmJpamUga29qaSBzdSB1xI1lc3R2b3ZhbGkgbmEgb2xpbXBpamFkYW1hIHBvxI1ldiBvZCAyMDAwLiBnb2RpbmUgaSBrb2ppIGltYWp1IHByZWtvIDEwMEtnIHRlxb5pbmUgaSBwcmVrbyAybSB2aXNpbmU6IA0KYGBge3J9DQpvbHltcGljU1IyMWMgPC0gZmlsdGVyKG9seW1waWNTUixZZWFyPj0yMDAwICYgV2VpZ2h0PjEwMCAmIEhlaWdodD4yMDApDQpoZWFkKG9seW1waWNTUjIxYyw1KQ0KYGBgDQoNCiMjIFRhc2sgIzUuIFNvcnRpcmFuamUgcG9kYXRha2ENClphIHNvcnRpcmFuamUgcG9kYXRha2EgdSBkYXRhIGZyYW1lLXUga29yaXN0aSBzZSBmdW5rY2lqYSBgYXJyYW5nZSgpYC4NCg0KU29ydGlyYWptbyBwb2RhdGtlIHUgZGF0YSBmcmFtZS11IGBvbHltcGljU1IyMWNgIHBvICoqcmFzdHXEh29qKiogdnJlZG5vc3RpIHZhcmlqYWJsZSBgSGVpZ2h0YDoNCmBgYHtyfQ0Kb2x5bXBpY1NSMjFjIDwtIGFycmFuZ2Uob2x5bXBpY1NSMjFjLEhlaWdodCkNCmhlYWQob2x5bXBpY1NSMjFjLDUpDQpgYGANCg0KU29ydGlyYWptbyBzYWRhIHBvZGF0a2UgdSBkYXRhIGZyYW1lLXUgYG9seW1waWNTUjIxY2AgcG8gKipvcGFkYWp1xIdvaioqIHZyZWRub3N0aSB2YXJpamFibGUgYEhlaWdodGA6DQpgYGB7cn0NCm9seW1waWNTUjIxYyA8LSBhcnJhbmdlKG9seW1waWNTUjIxYyxkZXNjKEhlaWdodCkpDQpoZWFkKG9seW1waWNTUjIxYyw1KQ0KYGBgDQoNCiMjIFRhc2sgIzYuIEpvxaEgbWFsbyBzb3J0aXJhbmphDQoNCklza29yaXN0aW1vIHNvcnRpcmFuamUga2FrbyBiaXNtbyBwcm9uYcWhbGkgbmFqbWxhxJFlZyBpIG5hanN0YXJpamVnIHNwb3J0aXN0dSB1IGRhdGEgZnJhbWUtdSBgb2x5bXBpY1NSYC4NCg0KS2FrbyBiaXNtbyBwcm9uYcWhbGkgbmFqbWxhxJFlZyBzcG9ydGlzdHUsIHNvcnRpcmHEh2VtbyBkYXRlIGZyYW1lIHUgcmFzdHXEh2VtIHJlZG9zbGVkdSBwbyB2YXJpamFibGkgYEFnZWAgaSBwcmlrYXphdGkgc2FtbyBwcnZpIHJlZDoNCmBgYHtyfQ0Kb2x5bXBpY1NSIDwtIGFycmFuZ2Uob2x5bXBpY1NSLEFnZSkNCmhlYWQob2x5bXBpY1NSLDEpDQpgYGANCg0Kc2xpxI1ubywgZGEgYmlzbW8gcHJvbmHFoWxpIG5hanN0YXJpamVnIHNwb3J0aXN0dSwgc29ydGlyYcSHZW1vIGRhdGUgZnJhbWUgdSBvcGFkYWp1xIdlbSByZWRvc2xlZHUgcG8gdmFyaWphYmxpIGBBZ2VgIGkgcHJpa2F6YXRpIHNhbW8gcHJ2aSByZWQ6DQpgYGB7cn0NCm9seW1waWNTUiA8LSBhcnJhbmdlKG9seW1waWNTUixkZXNjKEFnZSkpDQpoZWFkKG9seW1waWNTUiwxKQ0KYGBgDQoNCiMjIFRhc2sgIzcuIFN1bWlyYW5qZSBwb2RhdGFrYQ0KDQpaYSBzdW1pcmFuamUgcG9kYXRha2EgdSBkYXRhIGZyYW1lLXUga29yaXN0ZSBzZSBzbGVkZcSHZSBmdW5rY2lqZToNCjxzdHlsZT4NCiNmdW5jdGlvbnMgew0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsIEFyaWFsLCBIZWx2ZXRpY2EsIHNhbnMtc2VyaWY7DQogIGJvcmRlci1jb2xsYXBzZTogY29sbGFwc2U7DQogIHdpZHRoOiAxMDAlOw0KfQ0KDQojZnVuY3Rpb25zIHRkLCAjY3VzdG9tZXJzIHRoIHsNCiAgYm9yZGVyOiAxcHggc29saWQgI2RkZDsNCiAgcGFkZGluZzogOHB4Ow0KfQ0KDQojZnVuY3Rpb25zIHRyOm50aC1jaGlsZChldmVuKXtiYWNrZ3JvdW5kLWNvbG9yOiAjZjJmMmYyO30NCg0KI2Z1bmN0aW9ucyB0cjpob3ZlciB7YmFja2dyb3VuZC1jb2xvcjogI2RkZDt9DQoNCiNmdW5jdGlvbnMgdGggew0KICBwYWRkaW5nLXRvcDogMTJweDsNCiAgcGFkZGluZy1ib3R0b206IDEycHg7DQogIHRleHQtYWxpZ246IGxlZnQ7DQogIGJhY2tncm91bmQtY29sb3I6ICMwMDAwZmY7DQogIGNvbG9yOiB3aGl0ZTsNCn0NCjwvc3R5bGU+DQo8dGFibGUgaWQ9ImZ1bmN0aW9ucyI+DQoJPHRoZWFkPg0KCQk8dHI+DQoJCQk8dGg+T2JqZWN0aXZlPC90aD4NCgkJCTx0aD5GdW5jdGlvbjwvdGg+DQoJCQk8dGg+RGVzY3JpcHRpb248L3RoPg0KCQk8L3RyPg0KCTwvdGhlYWQ+DQoJPHRib2R5Pg0KCQk8dHI+DQoJCQk8dGQ+YmFzaWM8L3RkPg0KCQkJPHRkPg0KCQkJCTxjb2RlPnN1bSh4KTwvY29kZT4NCgkJCTwvdGQ+DQoJCQk8dGQ+U3VtIG9mIHZlY3RvciB4PC90ZD4NCgkJPC90cj4NCgkJPHRyPg0KCQkJPHRkPmNlbnRyZTwvdGQ+DQoJCQk8dGQ+DQoJCQkJPGNvZGU+bWVhbih4KTwvY29kZT4NCgkJCTwvdGQ+DQoJCQk8dGQ+TWVhbiAoYXZlcmFnZSkgb2YgdmVjdG9yIHg8L3RkPg0KCQk8L3RyPg0KCQk8dHI+DQoJCQk8dGQ+PC90ZD4NCgkJCTx0ZD4NCgkJCQk8Y29kZT5tZWRpYW4oeCk8L2NvZGU+DQoJCQk8L3RkPg0KCQkJPHRkPk1lZGlhbiBvZiB2ZWN0b3IgeDwvdGQ+DQoJCTwvdHI+DQoJCTx0cj4NCgkJCTx0ZD5zcHJlYWQ8L3RkPg0KCQkJPHRkPg0KCQkJCTxjb2RlPnNkKHgpPC9jb2RlPg0KCQkJPC90ZD4NCgkJCTx0ZD5TdGFuZGFyZCBkZXZpYXRpb24gb2YgdmVjdG9yIHg8L3RkPg0KCQk8L3RyPg0KCQk8dHI+DQoJCQk8dGQ+PC90ZD4NCgkJCTx0ZD4NCgkJCQk8Y29kZT5xdWFudGlsZSh4LCBwcm9icyk8L2NvZGU+DQoJCQk8L3RkPg0KCQkJPHRkPlF1YW50aWxlIG9mIHZlY3RvciB4PC90ZD4NCgkJPC90cj4NCgkJPHRyPg0KCQkJPHRkPjwvdGQ+DQoJCQk8dGQ+DQoJCQkJPGNvZGU+cmFuZ2UoeCk8L2NvZGU+DQoJCQk8L3RkPg0KCQkJPHRkPlJhbmdlIG9mIHZlY3RvciB4PC90ZD4NCgkJPC90cj4NCgkJPHRyPg0KCQkJPHRkPjwvdGQ+DQoJCQk8dGQ+DQoJCQkJPGNvZGU+ZGlmZihyYW5nZSh4KSkpPC9jb2RlPg0KCQkJPC90ZD4NCgkJCTx0ZD5XaWR0aCBvZiB0aGUgcmFuZ2Ugb2YgdmVjdG9yIHg8L3RkPg0KCQk8L3RyPg0KCQk8dHI+DQoJCQk8dGQ+PC90ZD4NCgkJCTx0ZD4NCgkJCQk8Y29kZT5taW4oeCk8L2NvZGU+DQoJCQk8L3RkPg0KCQkJPHRkPk1pbiBvZiB2ZWN0b3IgeDwvdGQ+DQoJCTwvdHI+DQoJCTx0cj4NCgkJCTx0ZD48L3RkPg0KCQkJPHRkPg0KCQkJCTxjb2RlPm1heCh4KTwvY29kZT4NCgkJCTwvdGQ+DQoJCQk8dGQ+TWF4IG9mIHZlY3RvciB4PC90ZD4NCgkJPC90cj4NCgkJPHRyPg0KCQkJPHRkPjwvdGQ+DQoJCQk8dGQ+DQoJCQkJPGNvZGU+YWJzKHgpPC9jb2RlPg0KCQkJPC90ZD4NCgkJCTx0ZD5BYnNvbHV0ZSB2YWx1ZSBvZiBhIG51bWJlciB4PC90ZD4NCgkJPC90cj4NCgk8L3Rib2R5Pg0KPC90YWJsZT4NCg0KDQoNClUgbmHFoWVtIHByaW1lcnUgxIdlbW8gc3VtaXJhdGkgcG9kYXRrZSBkYXRhIGZyYW1lLWEgYG9seW1waWNTUmAuDQoNClBydm8gxIdlbW8gcHJvbmHEh2kgZHZlIHN1bWFybmUgdmFyaWphYmxlOiAqKm1heF9BZ2UqKiBpICoqbWF4X0JNSSoqOg0KYGBge3J9DQpzdW1tYXJpc2Uob2x5bXBpY1NSLG1heF9BZ2U9bWF4KEFnZSksbWF4X0JNST1tYXgoQk1JKSkNCmBgYA0KDQpTYWRhIHByb25hxJFpbW8gKiptZWFuX0FnZSoqIGkgKiptZWFuX0JNSSoqOg0KYGBge3J9DQpzdW1tYXJpc2Uob2x5bXBpY1NSLG1lYW5fQWdlPW1lYW4oQWdlKSxtZWFuX0JNST1tZWFuKEJNSSkpDQpgYGANCg0KIyMgVGFzayAjOC4gVml6dWVsaXphY2lqYSBwb2RhdGFrYQ0KDQpQcmlrYcW+aW1vIHRhYmVsYXJubyBicm9qIG9zdm9qZW5paCBtZWRhbGphIG5hIHN2aW0gb2xpbXBpanNraW0gaWdyYW1hIHBvIHRpbW92aW1hOg0KYGBge3J9DQphdGhsZXRlX2V2ZW50cyAlPiUgDQogIGZpbHRlcighaXMubmEoTWVkYWwpKSAlPiUgDQogIGdyb3VwX2J5KE5PQywgTWVkYWwpICU+JSANCiAgc3VtbWFyaXplKGNhc2VzPW4oKSkgJT4lIA0KICBEVDo6ZGF0YXRhYmxlKCkNCmBgYA0KDQpOYXByYXZpbW8gbm92aSBkYXRhIGZyYW1lIGBDb3VudHJpZXNgIGtvamkgxIdlIHUgamVkbm9tIHJlZHUgcHJpa2F6YXRpIHNsZWRlxIdlIHBvZGF0a2U6DQpUZWFtLCBOT0MsIFllYXIsIEF0aGxldGVzLCBHb2xkLCBTaWx2ZXIsIEJyb256ZQ0KDQpgYGB7cn0NCmNvdW50cmllcyA8LSBhdGhsZXRlX2V2ZW50cyAlPiUgDQogIG11dGF0ZShNZWRhbD1mb3JjYXRzOjpmY3RfZXhwbGljaXRfbmEoTWVkYWwsbmFfbGV2ZWwgPSAiTm9NZWRhbCIpKSAlPiUgDQogIGdyb3VwX2J5KFRlYW0sIE5PQywgWWVhciwgTWVkYWwpICU+JSANCiAgc3VtbWFyaXplKENhc2VzPW4oKSkgJT4lIA0KICBzcHJlYWQoLGtleSA9ICJNZWRhbCIsIHZhbHVlID0gIkNhc2VzIikgJT4lIA0KICBtdXRhdGUoQXRobGV0ZXM9c3VtKEdvbGQsU2lsdmVyLEJyb256ZSxOb01lZGFsLG5hLnJtID0gVFJVRSkpDQpjb3VudHJpZXMgJT4lIA0KICBEVDo6ZGF0YXRhYmxlKCkNCmBgYA0KDQpQb2t1xaFham1vIGRhIHByaWthxb5lbW8gemVtbGplIHXEjWVzbmljZSBzdmloIG9saW1waWphZGEgc29ydGlyYW5lIHBvIGJyb2p1IGJvZG92YSBrb2plIGRvYmlqYW1vIHNsZWRlxIdvbSBmb3JtdWxvbToNCiQkUG9pbnRzPTMqR29sZCArIDIqU2lsdmVyICsgQnJvbnplJCQNCg0KYGBge3J9DQpjb3VudHJpZXMgPC0gbXV0YXRlKGNvdW50cmllcyxQb2ludHM9c3VtKDMqR29sZCwyKlNpbHZlcixCcm9uemUsbmEucm0gPSBUUlVFKSkgJT4lIA0KICBncm91cF9ieShOT0MpICU+JSANCiAgc3VtbWFyaXplKA0KICAgICAgQXRobGV0ZXM9c3VtKEF0aGxldGVzLG5hLnJtID0gVFJVRSksIA0KICAgICAgR29sZD1zdW0oR29sZCxuYS5ybSA9IFRSVUUpLA0KICAgICAgU2lsdmVyPXN1bShTaWx2ZXIsbmEucm0gPSBUUlVFKSwNCiAgICAgIEJyb256ZT1zdW0oQnJvbnplLG5hLnJtID0gVFJVRSksDQogICAgICBQb2ludHM9c3VtKFBvaW50cyxuYS5ybSA9IFRSVUUpDQogICkNCmFycmFuZ2UoY291bnRyaWVzLGRlc2MoUG9pbnRzKSkgJT4lIA0KICBEVDo6ZGF0YXRhYmxlKCkNCmBgYA0KDQpTYWRhIMSHZW1vIG5hIG1hcGkgc3ZldGEgcHJpa2F6YXRpIGJyb2ogcG9lbmEgcG8gemVtbGphbWEuDQoNClUgdHUgc3ZyaHUgxIdlbW8ga29yaXN0aXRpIHBha2V0ZSBgcm5hdHVyYWxlYXJ0aGAgaSBgcm5hdHVyYWxlYXJ0aGRhdGFgDQoNCmBgYHtyfQ0KbGlicmFyeSgicm5hdHVyYWxlYXJ0aCIpDQpsaWJyYXJ5KCJybmF0dXJhbGVhcnRoZGF0YSIpDQpgYGANCg0KSXogb3ZpaCBwYWtldGEgxIdlbW8ga3JlaXJhdGkgZGF0YSBmcmFtZSBgd29ybGRgOg0KDQpgYGB7cn0NCndvcmxkIDwtIG5lX2NvdW50cmllcyhzY2FsZSA9ICJtZWRpdW0iLCByZXR1cm5jbGFzcyA9ICJzZiIpDQpjbGFzcyh3b3JsZCkNCmBgYA0KDQpQb2dsZWRham1vIMWhdGEgc2FkcsW+aSBvdmFqIGRhdGEgZnJhbWU6DQpgYGB7cn0NCmdsaW1wc2Uod29ybGQpDQpgYGANCg0KTW/FvmVtbyB2aWRldGkgZGEgc2UgbmHFoSBwcmV0aG9kbmkgZGF0YSBmcmFtZSBgY291bnRyaWVzYCBtb8W+ZSBwb3ZlemF0aSBzYSBkYXRhIGZyYW1lLW9tIGB3b3JsZGAgcHJla28gcG9samEgTk9DIGkgaXNvX2EzLCBwYSDEh2VtbyBwb3ZlemF0aSBvdmUgZGF0YSBmcmFtZS1vdmU6DQoNCmBgYHtyfQ0KYWxsRGF0YSA8LSBtZXJnZSh3b3JsZCxjb3VudHJpZXMsYnkueD0iaXNvX2EzIixieS55PSJOT0MiLGFsbC54ID0gVFJVRSkNCmFsbERhdGEgJT4lIA0KICBzZWxlY3QoLWdlb21ldHJ5KSAlPiUgDQogIERUOjpkYXRhdGFibGUoKQ0KYGBgDQoNClByaWthxb5pbW8gYnJvaiBwb2VuYSBuYSBtYXBpOg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGFsbERhdGEpICsNCiAgICBnZW9tX3NmKGFlcyhmaWxsID0gUG9pbnRzKSkgKw0KICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJwbGFzbWEiLCB0cmFucyA9ICJzcXJ0IikNCmBgYA0KDQpLYWtvIHUgbmHFoWVtIGRhdGEgZnJhbWUtdSBpbWFtbyBpIGJyb2ogc3Rhbm92bmlrYSB1IHplbWxqaSwgaXpyYcSNdW5ham1vIGkgcHJvc2XEjWFuIGJyb2ogcG9lbmEgbmEgMTAwMCBzdGFub3ZuaWthLiANCmBgYHtyfQ0KYWxsRGF0YSA8LSBtdXRhdGUoYWxsRGF0YSxQb2ludHNQZXIxMDAwQ2FwaXRhPVBvaW50cy9wb3BfZXN0KjEwMDApIA0KDQphbGxEYXRhICU+JSANCiAgc2VsZWN0KC1nZW9tZXRyeSkgJT4lIA0KICBEVDo6ZGF0YXRhYmxlKCkNCmBgYA0KDQpOYSBrcmFqdSwgcHJpa2HFvmltbyBpIHRvIG5hIG1hcGk6DQpgYGB7cn0NCmdncGxvdChkYXRhID0gYWxsRGF0YSkgKw0KICAgIGdlb21fc2YoYWVzKGZpbGwgPSBQb2ludHNQZXIxMDAwQ2FwaXRhKSkgKw0KICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJwbGFzbWEiLCB0cmFucyA9ICJzcXJ0IikNCmBgYA==